#!/usr/bin/perl
use Switch;
##########################################################################################
#      This program was made to make Condor queue report to display on a website       	 #  
#			To do list at the end of the file.    				 #
#										   	 #
# 	    		 by Samir Cury em 16/03/2007   	    				 #	
#							     				 #
#	 		Contact: rimasy@gmail.com	     				 #
##########################################################################################

#testbed - future time improvements => won't need bash anymore, perl will handle it =)
 
#print "@timm[1]:@timm[2]:timm[0] \n\n\n\";

#@arr=localtime(time);

#@bu= qw( Jan Feb Mar Apr MSep Oct Nov Dec );

#print "@bu[4] @arr[3] @arr[2]:@arr[1]:@arr[0]";

#/testbed

#in this string you can configure which condor job attributes to worry about.

$worry_job_attr="MyType|Owner|x509userproxysubject|JobStatus|JobStartDate";


$cmd = "source ~/.bashrc ; condor_q -global -l | egrep \'$worry_job_attr\'";

@out_condor_q=qx[$cmd];

#voodoo - if $i=0, the first element is null, because of the check, the first job will give first, a "MyType", skipping 
#to the next element
$i=-1;
foreach my $line (@out_condor_q)
	{
	chomp($line);

	#make the job blocks, aggregating information of each job.
	#the goal is to make an array (@job), and each element is all 
	#the information about a job, like that:
	#Owner = "uscmsPool375":x509userproxysubject = 
	#"/DC=ch/DC=cern/OU=Organic 
	#Units/OU=Users/CN=asciaba/CN=430796/CN=Andrea 
	#Sciaba":JobStatus = 2:JobStartDate = 1234440155:

	if ($line !~ /MyType/)
		{
		@job[$i]=@job[$i].$line.":";
		}
		else
		{
		$i++;
		}

	}
#this is to put a "Local submission", if condor didn't returned any x509userproxysubject

#voodoo ninja sagaz below
$greater=scalar(split(/:/, @job[0]));


#the block won't be in a standard order, but this doesn't matter since we'll use a switch condition below.
foreach my $block(@job)
	{
	my @Block = split( /:/, $block);

	if ( $greater < scalar(@Block)) 
		{
		$greater=scalar(@Block);
		}
	if ( $greater > scalar(@Block) )
		{
		if ( $block !~ /x509/ )
			{
			push(@Block,'x509userproxysubject = "Local Submission"');
			}
		if ( $block !~ /JobStart/ )
			{
			scalar(@Block,"JobStartDate = Hasn't begun yet");
			}
		}
	push(@Blocks, join(::, @Block[0],@Block[1],@Block[2],@Block[3],@Block[4]));
	}
foreach $block(@Blocks)
	{
	#now we have to mount the hash of this job.
	@Block = split( /::/, $block);
	foreach $attr(@Block)
		{
		#this section must initialize the hashes of interest
		switch ($attr) {
				case /Owner/ {
						@attr=split(/=/, $attr);
						$job{owner} = @attr[1];
						$job{owner} =~ s/"/ /g;
						chop($job{owner});
						$job{owner}=reverse($job{owner});
						chop($job{owner});
						chop($job{owner});
						$job{owner}=reverse($job{owner});
						}
				case /x509/  {
						@attr=split(/"/, $attr);
						$job{x509} = @attr[1];
						}
			case /tatus/ { 
					@attr=split(/=/, $attr);
					$job{status} = @attr[1];
					$job{status} =~ s/"/ /g;
					$job{status}=chop($job{status});
					}
				case /Date/  { $job{date} = $attr }
				}
		}
	#and this finalizes the final hash > %jobs
	#first we count every kind of job of every user
	if (!(defined($jobs{$job{owner}}{$job{status}})))
		{
		$jobs{$job{owner}}{$job{status}}=0;
		}
	$jobs{$job{owner}}{$job{status}}++;
	#now we catch the DN of each user;
	if (!(defined($jobs{$job{owner}}{dn})))
		{
		$jobs{$job{owner}}{dn}=$job{x509};
		}
	#now we wanna catch the value of the oldest job of the user, always testing if the next is minor than, 
	#as the timestamp is in epoch, the oldest is with the lesser value.
	if (($job{date} =~ /egun/) && (!(defined($jobs{$job{owner}}{oldest}))))
		{
		$jobs{$job{owner}}{oldest}="No job started to run yet";
		}

	if ((!(defined($jobs{$job{owner}}{oldest}))) && ($job{date} =~ /\d{10}/))
		{
		@date=split(/=/, $job{date});
		$jobs{$job{owner}}{oldest}=@date[1];
		}
		@date=split(/=/, $job{date});
	if (defined($jobs{$job{owner}}{oldest}) && ($job{date} =~ /\d{10}/) && 
(@date[1] > $jobs{$job{owner}}{oldest}))
		{
		$jobs{$job{owner}}{oldest}=@date[1];
		}

	}
#Now we have to create the HTML table =) with all the information
#the best is to initialize an array to set the order of display of the columns			
		
@columns = ("\(\'string\'\, \'The oldest job runs since\'\)"
,"\(\'string\'\, \'Mapped User\'\)"
,"\(\'string\'\,\'Complete DN of the user\'\)"
,"\(\'number\'\, \'Running Jobs\'\)"
,"\(\'number\'\, \'Idle Jobs\'\)"
,"\(\'number\'\, \'Held Jobs\'\)"
,"\(\'number\'\, \'Total\'\)");

$output=qx[cat googlejs_head.html];

foreach my $header(@columns)
	{
	$middle = $middle."data.addColumn".$header."\; \n" ;		
	}
$done = "false";

$ai=0;
$aj=0;
foreach my $owner(keys %jobs)
	{
	@worry_states=(1,2,5);
	foreach my $i (@worry_states)
		{
		if (!(defined($jobs{$owner}{$i})))
			{
			$jobs{$owner}{$i}=0;
			}
		}
	my $epoch=$jobs{$owner}{oldest};
	$epoch=reverse($epoch);
	chop($epoch);
	$epoch=reverse($epoch);
	my $cmd = "date -d @".$epoch;
	$cmd = qx[$cmd];
	chomp($cmd);
	$jobs{$owner}{oldest} = $cmd;
	
	#Madness? THIS-IS-IMPORTANT!! Counts the total jobs for each column, 0 index is total of all
	$totaljobs=$jobs{$owner}{2}+$jobs{$owner}{1}+$jobs{$owner}{5};
	@totalJobs[0]=@totalJobs[0]+$jobs{$owner}{2}+$jobs{$owner}{1}+$jobs{$owner}{5};
	@totalJobs[1]=@totalJobs[1]+$jobs{$owner}{1};
	@totalJobs[2]=@totalJobs[2]+$jobs{$owner}{2};
	@totalJobs[5]=@totalJobs[5]+$jobs{$owner}{5};

	#Now we have to set the number of rows (google - why the need of that??)
	#See that the +1 is because the "Total" row
	
	if ($done eq "false")
		{
		$middle = $middle."data.addRows\(".((scalar(keys %jobs))+1)."\)\; \n";
		$done="true";
		}

	#Now we have to print the Javascript table to the $middle

	#this prints each row, easy, after all the care above =)
        $table = $table."data.setCell\(".$ai." \,".$aj." \,\'".$jobs{$owner}{oldest}."\'\)\; \n";
	$aj++;
        $table = $table."data\.setCell\($ai \,$aj \,\'".$owner."\'\)\; \n";
	$aj++;
        $table = $table."data\.setCell\($ai \,$aj \,\'".$jobs{$owner}{dn}."\'\)\; \n";
	$aj++;
        $table = $table."data\.setCell\($ai \,$aj \,".$jobs{$owner}{2}."\)\; \n";
	$aj++;
        $table = $table."data\.setCell\($ai \,$aj \,".$jobs{$owner}{1}."\)\; \n";
	$aj++;
        $table = $table."data\.setCell\($ai \,$aj \,".$jobs{$owner}{5}."\)\; \n";
	$aj++;
        $table = $table."data\.setCell\($ai \,$aj \,".$totaljobs."\)\; \n";
	$aj=0;
	$ai++;
	
	}
#Now we can make the total plot

$table = $table."data\.setCell\($ai \,$aj \, \'Total\' \)\; \n";
$aj++;
$table = $table."data\.setCell\($ai \,$aj \, \'\' \)\; \n";
$aj++;
$table = $table."data\.setCell\($ai \,$aj \, \'\' \)\; \n";
$aj++;
$table = $table."data\.setCell\($ai \,$aj \,".@totalJobs[2]."\)\; \n";
$aj++;
$table = $table."data\.setCell\($ai \,$aj \,".@totalJobs[1]."\)\; \n";
$aj++;
$table = $table."data\.setCell\($ai \,$aj \,".@totalJobs[5]."\)\; \n";
$aj++;
$table = $table."data\.setCell\($ai \,$aj \,".@totalJobs[0]."\)\; \n";
$aj++;

#print "<td>@totalJobs[2]</td><td>@totalJobs[1]</td><td>@totalJobs[5]</td><td>@totalJobs[0]</td></tr>";

$foot = qx[cat googlejs_foot.html];

$middle = $middle.$table;
$output = $output.$middle;
$output = $output.$foot;

print $output;

#Here we let the body open, so you can put on the foot whatever you want



#print "</table>";


#prints the last refresh of the page
$last_refresh=qx[date];

print '<p align="center"><font size="3" color="blue"><b>'."Last Refresh:$last_refresh".'</b></font></p>';

print '<p align="center"><font color="green" size=3>Condor4web V2</font></p>';

print '
</body>
</html>';


#########################################################################
#				To-do list:				#
#  1 - Convert all time algorithms to don't depend Bash anymore		#
#########################################################################
